/*
 * Yabumi, a 2d scrolling shoot-em-up game.
 * Copyright (C) 2003 Gemma Teruaki <terugen@yabumi.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 */

#include <math.h>
#include "../taskmanager.h"
#include "../util.h"
#include "../sprite.h"
#include "../video.h"
#include "hitcircle.h"
#include "explosion.h"
#include "flame.h"

extern _list_header *active_task_list_header, *expired_task_list_header;
extern _list_header hitcircle_list_header;
_list_header flame_list_header;

void Flame_Init()
{
  Create_list(&flame_list_header);
}

void Flame_Free()
{
  Free_list(&flame_list_header);
}

_Flame *Flame_Create(int x, int y, int dx, int dy, int angle)
{
  _list_item *list_item;
  list_item = (_list_item *)pmalloc(sizeof(_list_item));
  Add_item_last(&flame_list_header, list_item);
  _Flame *flame = &list_item->data.Flame;
  flame->root = list_item;

  flame->x = x;
  flame->y = y;
  flame->dx = dx;
  flame->dy = dy;
  flame->angle = angle;
  return flame;
}

task Flame_Add(_option *optv)
{
  _Flame *flame;
  flame = (_Flame *)optv->socket[0];
  Task_Add(Flame_Move, flame, NULL, INFINITY_COUNT);
  Task_Add(Flame_Draw, flame, NULL, INFINITY_COUNT);
}

task Flame_Move(_option *optv)
{
  _Flame *flame;
  flame = (_Flame *)optv->socket[0];

  if (optv->count <= -1 * FLAME_LIFETIME ) {
    optv->count = KILL_COUNT;
    Task_Add(Flame_Kill, flame, NULL, ONETIME_COUNT);
    return;
  };

  /* Move Flame */  
  flame->x += FLAME_SPEED * cos(flame->angle * RM_PI);
  flame->y += FLAME_SPEED * sin(flame->angle * RM_PI);
  flame->x += flame->dx >> 8;
  flame->y += flame->dy >> 8;
  cap_angle(&flame->angle);

  /* status check start */
  _list_item *list_item = hitcircle_list_header.next->next;
  _Hitcircle *hitcircle;

  if (optv->count < INFINITY_COUNT - 3) {
    while (list_item != hitcircle_list_header.prev) {
      hitcircle = &list_item->data.Hitcircle;
      if (distance(flame->x, flame->y, hitcircle->x, hitcircle->y) <= 
	  hitcircle->radius + FLAME_COLLISION_DISTANCE) {
	/*HIT!*/
	hitcircle->was_hit = __hit_flame;
	Task_Add(Explosion_Draw,
		 Explosion_Create(flame->x, flame->y),
		 NULL, ONETIME_COUNT + 15);
	Task_Add(Flame_Add,
		 Flame_Create(flame->x, flame->y, flame->dx, flame->dy, flame->angle + (optv->count % -60)),
		 NULL, ONETIME_COUNT);
	Task_Add(Flame_Add, 
		 Flame_Create(flame->x, flame->y, flame->dx, flame->dy, flame->angle - (optv->count % -60)),
		 NULL, ONETIME_COUNT);
	optv->count = KILL_COUNT;
	Task_Add(Flame_Kill, flame, NULL, ONETIME_COUNT);
	return;
	break;
      };
      list_item = list_item->next;
    };
  };
  /* status check end */
};

task Flame_Draw(_option *optv)
{
  _Flame *flame;
  flame = (_Flame *)optv->socket[0];

  int i;
  SDL_Surface *image;
  i = (optv->count / -4) % 3;
  image = Sprite_Flame[i];
  Sprite_Add(flame->x, flame->y, Z_ORDER_D2, image);
}

task Flame_Kill(_option *optv)
{
  _Flame *flame;
  flame = (_Flame *)optv->socket[0];

  int i;
  _list_item *list_item;
  _task_item *task_item;

  if (optv->count == ONETIME_COUNT) {
    list_item = active_task_list_header->next->next;
    while (list_item != active_task_list_header->prev) {
      task_item = &list_item->data.task_item;
      for (i = 0; i < MAX_SOCKET; i++) {
	if (task_item->option.socket[i] == flame) {
	  task_item->option.count = KILL_COUNT;
	};
      };
      list_item = list_item->next;
    };
    list_item = expired_task_list_header->next->next;
    while (list_item != expired_task_list_header->prev) {
      task_item = &list_item->data.task_item;
      for (i = 0; i < MAX_SOCKET; i++) {
	if (task_item->option.socket[i] == flame) {
	  task_item->option.count = KILL_COUNT;
	};
      };
      list_item = list_item->next;
    };
    Kill_item(&flame_list_header, (_list_item *)flame->root);
    pfree(flame->root);
  };
}
